#include <stdio.h>
#include "TcpServer.h"
#include "Global.h"

int TcpServer::m_currentconnect = 0;

void singpipe_handler(int i)
{
        DEBUG_LOG("Signalpipe: %d", i);
}

TcpServer::TcpServer(short port, int maxlisten):
m_port(port),
m_maxlisten(maxlisten)
{
        DEBUG_LOG("TcpServer::TcpServer()");
        signal(SIGPIPE,SIG_IGN);
        m_serversock = socket(AF_INET, SOCK_STREAM, 0);
        if(-1 == m_serversock)
        {
                ERROR_LOG("m_serversock create error");
                exit(-1);
        }

        struct sockaddr_in addr = {0};
        addr.sin_family = AF_INET;  //TCP
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = inet_addr("0.0.0.0");

        int on = 1;
        setsockopt(m_serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);

        if(-1 == bind(m_serversock, (struct sockaddr *)&addr, sizeof addr))
        {
                ERROR_LOG("Bind error");
                exit(-1);
        }

        listen(m_serversock, m_maxlisten);
}

TcpServer::~TcpServer()
{
        DEBUG_LOG("TcpServer::~TcpServer()");
}

void 
TcpServer::start()
{
        DEBUG_LOG("TcpServer::start()");
        pthread_t t;
        pthread_create(&t, NULL, acceptLoop, this);
}

void* 
TcpServer::acceptLoop(void *pObj)
{
        DEBUG_LOG("TcpServer::acceptLoop()");
        TcpServer *pServer = static_cast<TcpServer *>(pObj);
        DEBUG_LOG("Listening port %d!",pServer->m_port);

        struct sockaddr_in clienaddr = {0};
        socklen_t len = sizeof(clienaddr);

        while(true)
        {
                int clientsock = accept(pServer->m_serversock, (struct sockaddr *)&clienaddr, &len);
                if(clientsock == -1)
                {
                        ERROR_LOG("clientsock = -1 \n");
                }
                m_currentconnect += 1;

                Clientinfo *pinfo = new Clientinfo;
                pinfo->pTcpServer = pServer;
                pinfo->sock = clientsock;
                pinfo->clienaddr = clienaddr;

                pthread_t t;
                pthread_create(&t, NULL, callonAccept, pinfo);
        }
        return NULL;
}

void* 
TcpServer::callonAccept(void *pinfo)
{
        DEBUG_LOG("TcpServer::callonAccept()\tNew Thread Create");

        Clientinfo *pInfo = (Clientinfo *)pinfo;

        if(NULL == pInfo)
        {
                ERROR_LOG("error: pTcpServer = NULL!");
                return NULL;
        }

        pInfo->pTcpServer->onAccept(pInfo);

        m_currentconnect -= 1;

        delete pInfo;

        DEBUG_LOG("TcpServer::callonAccept()\tThread exit");
}

void 
TcpServer::onAccept(Clientinfo *info)
{
        DEBUG_LOG("TcpServer::onAccept");
}